/**
 * 图数据结构 - 重构自原始的graph.js
 */
export class Graph {
  constructor(settings = {}) {
    this.nodes = {}
    this.edges = {}
    this.settings = {
      epoch: 'Event Time',
      epochFormat: 'YYYY-M-D H:m:s',
      source: 'source',
      target: 'target',
      ...settings
    }
    
    this.nodesCount = 0
    this.edgesCount = 0
  }

  /**
   * 获取节点
   */
  getNode(nodeId) {
    return this.nodes[nodeId]
  }

  /**
   * 获取边
   */
  getEdge(source, target) {
    return this.edges[source + '<>' + target] || this.edges[target + '<>' + source]
  }

  /**
   * 添加节点
   */
  addNode(nodeName, nodeData) {
    if (!nodeName) {
      return null
    }

    let node = this.getNode(nodeName)

    if (!node) {
      node = new Node(this.nodesCount, nodeName)
      this.nodesCount++
      this.nodes[nodeName] = node
    }

    if (nodeData) {
      node.data.push(nodeData)
    }

    return node
  }

  /**
   * 添加边
   */
  addEdge(source, target, data) {
    // 防止自环
    if (source === target) {
      this.addNode(source, data)
      return
    }

    const fromNode = this.addNode(source, data)
    const toNode = this.addNode(target, data)

    if (fromNode && toNode) {
      // 记录节点的邻接关系
      if (!fromNode.edges.includes(toNode.id)) {
        fromNode.edges.push(toNode.id)
      }
      if (!toNode.edges.includes(fromNode.id)) {
        toNode.edges.push(fromNode.id)
      }

      // 创建边
      this.createEdge(source, target, data)
    }
  }

  /**
   * 创建边
   */
  createEdge(source, target, data) {
    let edge = this.getEdge(source, target)

    if (!edge) {
      edge = new Edge(source, target, this.edgesCount)
      this.edgesCount++
      this.edges[source + '<>' + target] = edge
    }

    if (data) {
      edge.data.push(data)
    }

    return edge
  }

  /**
   * 从CSV行添加数据
   */
  addCSVRow(data) {
    const source = data[this.settings.source]
    const target = data[this.settings.target]
    this.addEdge(source, target, data)
  }

  /**
   * 获取节点和边的数组表示
   */
  getNodesAndEdgesArray() {
    const edgesArray = []

    Object.values(this.nodes).forEach(node => {
      edgesArray[node.id] = [...new Set(node.edges)] // 去重
    })

    return edgesArray
  }

  /**
   * 获取查找表
   */
  getLookupTable(nodesWidth) {
    const lookupTable = {}
    let i = 0

    Object.entries(this.nodes).forEach(([key, node]) => {
      const texStartX = (i % nodesWidth) / nodesWidth
      const texStartY = Math.floor(i / nodesWidth) / nodesWidth

      lookupTable[key] = {
        texPos: [texStartX, texStartY],
        id: node.id
      }

      i++
    })

    return lookupTable
  }

  /**
   * 获取时间纹理数组
   */
  getEpochTextureArray(type) {
    const source = type === 'nodes' ? this.nodes : this.edges
    const epochArray = []

    Object.values(source).forEach(item => {
      const epochs = []
      
      item.data.forEach(dataItem => {
        if (dataItem[this.settings.epoch]) {
          const time = this.parseTime(dataItem[this.settings.epoch])
          if (time) {
            epochs.push(time)
          }
        }
      })

      epochArray[item.id] = [...new Set(epochs)] // 去重
    })

    return epochArray
  }

  /**
   * 解析时间
   */
  parseTime(timeString) {
    try {
      // 简化的时间解析，支持多种格式
      const date = new Date(timeString)
      return date.getTime() / 1000 // 返回Unix时间戳
    } catch (error) {
      console.warn('无法解析时间:', timeString)
      return null
    }
  }

  /**
   * 获取节点位置数组
   */
  getNodePositions() {
    const positions = []
    const nodeArray = Object.values(this.nodes).sort((a, b) => a.id - b.id)
    
    nodeArray.forEach(node => {
      // 初始化随机位置
      positions.push(
        (Math.random() - 0.5) * 1000,
        (Math.random() - 0.5) * 1000,
        (Math.random() - 0.5) * 1000
      )
    })
    
    return positions
  }

  /**
   * 获取边的索引数组
   */
  getEdgeIndices() {
    const indices = []
    
    Object.values(this.edges).forEach(edge => {
      const sourceNode = this.getNodeByName(edge.source)
      const targetNode = this.getNodeByName(edge.target)
      
      if (sourceNode && targetNode) {
        indices.push(sourceNode.id, targetNode.id)
      }
    })
    
    return indices
  }

  /**
   * 根据名称获取节点
   */
  getNodeByName(name) {
    return this.nodes[name]
  }

  /**
   * 动态生成节点类型的颜色映射
   * @param {Array} nodes - 节点数组
   * @returns {Object} 类型到颜色的映射对象
   */
  generateTypeColorMapping(nodes) {
    // 收集所有唯一的节点类型
    const uniqueTypes = new Set()
    nodes.forEach(node => {
      if (node.type) {
        uniqueTypes.add(node.type)
      }
    })
    
    const types = Array.from(uniqueTypes).sort() // 排序确保一致性
    const typeColorMap = {}
    
    // 预定义的美观颜色调色板
    const colorPalette = [
      '#FF6B6B', // 红色系
      '#4ECDC4', // 青绿色
      '#45B7D1', // 蓝色
      '#96CEB4', // 绿色
      '#FECA57', // 黄色
      '#FF9FF3', // 粉色
      '#54A0FF', // 亮蓝色
      '#5F27CD', // 紫色
      '#00D2D3', // 青色
      '#FF9F43', // 橙色
      '#10AC84', // 深绿色
      '#EE5A6F', // 玫瑰色
      '#C44569', // 深粉色
      '#F8B500', // 金黄色
      '#6C5CE7', // 淡紫色
      '#A3CB38', // 草绿色
      '#12CBC4', // 薄荷绿
      '#FDA7DF', // 淡粉色
      '#ED4C67', // 红粉色
      '#F79F1F'  // 深橙色
    ]
    
    // 为每个类型分配颜色
    types.forEach((type, index) => {
      if (index < colorPalette.length) {
        typeColorMap[type] = colorPalette[index]
      } else {
        // 如果类型数量超过调色板，使用HSL生成更多颜色
        const hue = (index * 137.508) % 360 // 使用黄金角度分布
        const saturation = 65 + (index % 3) * 15 // 65-95% 饱和度
        const lightness = 50 + (index % 4) * 10  // 50-80% 亮度
        typeColorMap[type] = `hsl(${hue}, ${saturation}%, ${lightness}%)`
      }
    })
    
    console.log(`[Graph.generateTypeColorMapping] 发现 ${types.length} 种节点类型:`, types)
    
    return typeColorMap
  }

  /**
   * 设置图数据（标准接口格式）
   * @param {Object} graphData - 符合接口规范的图数据
   */
  setData(graphData) {
    // 清空现有数据
    this.nodes = {}
    this.edges = {}
    this.nodesCount = 0
    this.edgesCount = 0
    
    console.log('[Graph.setData] 开始设置图数据:', graphData)
    
    if (!graphData || (!graphData.nodes && !graphData.edges && !graphData.links)) {
      console.error('[Graph.setData] 无效的图数据格式')
      return
    }
    
    // 第一步：分析所有节点类型并生成颜色映射
    const typeColorMap = this.generateTypeColorMapping(graphData.nodes || [])
    console.log('[Graph.setData] 节点类型颜色映射:', typeColorMap)
    
    // 添加节点
    if (graphData.nodes && Array.isArray(graphData.nodes)) {
      graphData.nodes.forEach(nodeData => {
        // 使用节点的name作为键值，而不是id
        const nodeKey = nodeData.name || nodeData.id
        
        // 根据类型分配颜色
        const nodeType = nodeData.type || 'default'
        const nodeColor = nodeData.color || typeColorMap[nodeType] || '#888888'
        
        const node = this.addNode(nodeKey, {
          id: nodeData.id,  // 保存原始ID
          name: nodeData.name,
          type: nodeData.type,
          label: nodeData.label || nodeData.name,
          category: nodeData.category || nodeData.type,
          group: nodeData.group || 1,
          size: nodeData.size || 10,
          color: nodeColor,  // 使用分配的颜色
          position: nodeData.position,
          properties: nodeData.properties || {},
          ...nodeData // 保留其他字段
        })
        
        if (node) {
          console.log(`[Graph.setData] 添加节点: ${nodeKey} (ID: ${nodeData.id}, 类型: ${nodeData.type}, 颜色: ${nodeColor})`)
        }
      })
    }
    
    // 添加边（兼容 edges 和 links 字段）
    const edgesData = graphData.edges || graphData.links || []
    if (Array.isArray(edgesData) && edgesData.length > 0) {
      // 创建ID到名称的映射表
      const idToNameMap = {}
      if (graphData.nodes) {
        graphData.nodes.forEach(nodeData => {
          idToNameMap[nodeData.id] = nodeData.name || nodeData.id
        })
      }
      
      edgesData.forEach(edgeData => {
        // 将节点ID转换为节点名称
        const sourceName = idToNameMap[edgeData.source] || edgeData.source
        const targetName = idToNameMap[edgeData.target] || edgeData.target
        
        const edge = this.addEdge(sourceName, targetName, {
          id: edgeData.id,
          type: edgeData.type,
          label: edgeData.label || edgeData.type,
          weight: edgeData.weight || 1.0,
          color: edgeData.color,
          width: edgeData.width || 1,
          directed: edgeData.directed !== false,
          properties: edgeData.properties || {},
          ...edgeData // 保留其他字段
        })
        
        if (edge) {
          console.log(`[Graph.setData] 添加边: ${sourceName} -> ${targetName} (${edgeData.type})`)
        }
      })
    }
    
    // 记录元数据信息
    if (graphData.metadata) {
      console.log(`[Graph.setData] 图谱信息: ${graphData.metadata.name} v${graphData.metadata.version}`)
      console.log(`[Graph.setData] 描述: ${graphData.metadata.description}`)
    }
    
    console.log(`[Graph.setData] 图数据设置完成: ${this.nodesCount} 个节点, ${this.edgesCount} 条边`)
  }

  /**
   * 获取统计信息
   */
  getStats() {
    return {
      nodeCount: this.nodesCount,
      edgeCount: this.edgesCount,
      totalDataPoints: Object.values(this.edges).reduce((sum, edge) => sum + edge.data.length, 0)
    }
  }
}

/**
 * 节点类
 */
export class Node {
  constructor(id, name) {
    this.id = id
    this.name = name
    this.edges = [] // 邻接节点的ID列表
    this.data = [] // 节点相关的数据
    this.position = { x: 0, y: 0, z: 0 } // 3D位置
    this.velocity = { x: 0, y: 0, z: 0 } // 速度
    this.color = { r: 1, g: 1, b: 1 } // 颜色
  }

  /**
   * 添加邻居
   */
  addNeighbor(nodeId) {
    if (!this.edges.includes(nodeId)) {
      this.edges.push(nodeId)
    }
  }

  /**
   * 获取度数
   */
  getDegree() {
    return this.edges.length
  }

  /**
   * 设置位置
   */
  setPosition(x, y, z) {
    this.position.x = x
    this.position.y = y
    this.position.z = z
  }

  /**
   * 设置颜色
   */
  setColor(r, g, b) {
    this.color.r = r
    this.color.g = g
    this.color.b = b
  }
}

/**
 * 边类
 */
export class Edge {
  constructor(source, target, id) {
    this.source = source
    this.target = target
    this.id = id
    this.data = [] // 边相关的数据
    this.weight = 1 // 权重
    this.color = { r: 0.4, g: 0.4, b: 0.4 } // 颜色
  }

  /**
   * 获取权重（基于数据点数量）
   */
  getWeight() {
    return this.data.length
  }

  /**
   * 设置颜色
   */
  setColor(r, g, b) {
    this.color.r = r
    this.color.g = g
    this.color.b = b
  }

  /**
   * 获取时间范围
   */
  getTimeRange() {
    const times = this.data.map(item => {
      if (item['Event Time']) {
        return new Date(item['Event Time']).getTime() / 1000
      }
      return null
    }).filter(time => time !== null)

    if (times.length === 0) return null

    return {
      min: Math.min(...times),
      max: Math.max(...times)
    }
  }
}

